package com.rmfyzxfw.caseprocess.service.impl;

import cn.hutool.core.util.IdUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import com.rmfyzxfw.caseprocess.boot.result.page.Pagination;
import com.rmfyzxfw.caseprocess.enums.True1False0;
import com.rmfyzxfw.caseprocess.mapper.DataNodeItemRelMapper;
import com.rmfyzxfw.caseprocess.mapper.DataNodeMapper;
import com.rmfyzxfw.caseprocess.mapper.ProcessDataMapper;
import com.rmfyzxfw.caseprocess.mapper.ProcessMapper;
import com.rmfyzxfw.caseprocess.model.cmd.DataNodeItemCmd;
import com.rmfyzxfw.caseprocess.model.cmd.DataNodeItemDelCmd;
import com.rmfyzxfw.caseprocess.model.converter.DataNodeConverter;
import com.rmfyzxfw.caseprocess.model.param.DataNodeConfigListParam;
import com.rmfyzxfw.caseprocess.model.param.DataNodeListParam;
import com.rmfyzxfw.caseprocess.model.po.DataNode;
import com.rmfyzxfw.caseprocess.model.po.DataNodeItemRel;
import com.rmfyzxfw.caseprocess.model.po.Process;
import com.rmfyzxfw.caseprocess.model.po.ProcessData;
import com.rmfyzxfw.caseprocess.model.vo.DataNodeListVO;
import com.rmfyzxfw.caseprocess.model.vo.ProcessDataNodeListVO;
import com.rmfyzxfw.caseprocess.model.vo.ProcessNodeVO;
import com.rmfyzxfw.caseprocess.service.DataNodeService;
import lombok.RequiredArgsConstructor;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @author GYW
 * @description 针对表【t_data_node(数据节点)】的数据库操作Service实现
 * @createDate 2024-08-14 16:11:02
 */
@Service
@RequiredArgsConstructor
public class DataNodeServiceImpl extends ServiceImpl<DataNodeMapper, DataNode>
        implements DataNodeService {

    private final DataNodeItemRelMapper dataNodeItemRelMapper;
    private final DataNodeConverter dataNodeConverter;
    private final ProcessMapper processMapper;
    private final ProcessDataMapper processDataMapper;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void addDataNodeItem(DataNodeItemCmd cmd) {
        List<String> dataItemIds = cmd.getDataItemIds();
        List<String> existDataItemIds = dataNodeItemRelMapper.selectList(Wrappers.<DataNodeItemRel>lambdaQuery()
                        .eq(DataNodeItemRel::getDataNodeId, cmd.getDataNodeId())
                        .in(DataNodeItemRel::getDataItemId, dataItemIds)
                        .select(DataNodeItemRel::getDataItemId))
                .stream()
                .map(DataNodeItemRel::getDataItemId)
                .collect(Collectors.toList());
        dataItemIds.removeAll(existDataItemIds);

        dataItemIds.forEach(dataItemId -> {
            DataNodeItemRel dataNodeItemRel = new DataNodeItemRel();
            dataNodeItemRel.setDataNodeItemRelId(IdUtil.simpleUUID());
            dataNodeItemRel.setDataItemId(dataItemId);
            dataNodeItemRel.setDataNodeId(cmd.getDataNodeId());
            dataNodeItemRelMapper.insert(dataNodeItemRel);
        });

    }

    @Override
    public void removeDataNodeItem(DataNodeItemDelCmd cmd) {
        dataNodeItemRelMapper.delete(Wrappers.<DataNodeItemRel>lambdaQuery()
                .eq(DataNodeItemRel::getDataNodeId, cmd.getDataNodeId())
                .eq(DataNodeItemRel::getDataItemId, cmd.getDataItemId()));
    }

    @Override
    public Pagination<DataNodeListVO> list(DataNodeListParam param) {
        Page<DataNode> page = new Page<>(param.getPageNum(), param.getPageSize());
        Page<DataNode> dataNodePage = page(page, Wrappers.<DataNode>lambdaQuery().eq(Objects.nonNull(param.getStatus()), DataNode::getStatus, param.getStatus())
                .eq(StringUtils.isNotBlank(param.getCourtId()), DataNode::getCourtId, param.getCourtId())
                .apply(StringUtils.isNotBlank(param.getCaseType()), "FIND_IN_SET ('" + param.getCaseType() + "',case_type)")
                .like(StringUtils.isNotBlank(param.getDataNodeName()), DataNode::getDataNodeName, param.getDataNodeName())
                .orderByDesc(DataNode::getId));
        return Pagination.build(dataNodePage, dataNodeConverter::dos2vos);
    }

    @Override
    public List<ProcessDataNodeListVO> processDataNodeList(String processId) {
        Process process = processMapper.selectOne(Wrappers.<Process>lambdaQuery().eq(Process::getProcessId, processId));
        if (StringUtils.isBlank(process.getProcessDataId())) {
            throw new RuntimeException("没有启用的流程");
        }
        ProcessData processData = processDataMapper.selectOne(Wrappers.<ProcessData>lambdaQuery().eq(ProcessData::getProcessDataId, process.getProcessDataId()));
        List<ProcessNodeVO> processNodeVOS = JSON.parseArray(processData.getData(), ProcessNodeVO.class);
        List<ProcessDataNodeListVO> processDataNodeAll = Lists.newArrayList();
        processNodeVOS.forEach(pn -> {
            List<ProcessNodeVO.DataNodeVO> dataNodes = pn.getDataNodes();
            if (CollectionUtils.isNotEmpty(dataNodes)) {
                List<ProcessDataNodeListVO> processDataNodes = dataNodes.stream().map(dn -> {
                    ProcessDataNodeListVO processDataNodeListVO = new ProcessDataNodeListVO();
                    processDataNodeListVO.setDataNodeId(dn.getDataNodeId());
                    processDataNodeListVO.setDataNodeName(dn.getDataNodeName());
                    processDataNodeListVO.setChildrenProcessId(dn.getChildrenProcessId());

                    List<ProcessDataNodeListVO.DataNodeStatusVO> dataNodeStatusVOS = dn.getDataNodeStatuses().stream().map(dns -> {
                        ProcessDataNodeListVO.DataNodeStatusVO dataNodeStatusVO = new ProcessDataNodeListVO.DataNodeStatusVO();
                        dataNodeStatusVO.setStatusId(dns.getStatusId());
                        dataNodeStatusVO.setStatusName(dns.getStatusName());
                        dataNodeStatusVO.setStatusLevel(dns.getStatusLevel());
                        dataNodeStatusVO.setColor(dns.getColor());
                        return dataNodeStatusVO;
                    }).collect(Collectors.toList());
                    processDataNodeListVO.setDataNodeStatusVOList(dataNodeStatusVOS);
                    return processDataNodeListVO;
                }).collect(Collectors.toList());
                processDataNodeAll.addAll(processDataNodes);
            }
        });
        return processDataNodeAll;
    }

    @Override
    public Pagination<DataNodeListVO> configList(DataNodeConfigListParam param) {
        Page<DataNode> page = new Page<>(param.getPageNum(), param.getPageSize());
        Page<DataNode> dataNodePage = page(page, Wrappers.<DataNode>lambdaQuery().eq(DataNode::getStatus, True1False0.TRUE.getCode())
                .eq(DataNode::getCourtId, param.getCourtId())
                .like(StringUtils.isNotBlank(param.getDataNodeName()), DataNode::getDataNodeName, param.getDataNodeName())
                .orderByDesc(DataNode::getId));
        List<DataNode> originalDataNodes = dataNodePage.getRecords();
        if (CollectionUtils.isEmpty(originalDataNodes)) {
            return Pagination.empty();
        }
        List<String> originalProcessIds = originalDataNodes
                .stream().map(DataNode::getChildrenProcessId)
                .filter(StringUtils::isNotBlank).collect(Collectors.toList());
        // 所有节点都不是子流程 直接返回
        if (CollectionUtils.isEmpty(originalProcessIds)) {
            return Pagination.build(dataNodePage, dataNodeConverter::dos2vos);
        }
        // 已经启用的子流程
        List<String> finalProcessIds = processMapper.selectList(Wrappers.<Process>lambdaQuery()
                        .in(Process::getProcessId, originalProcessIds)
                        .isNotNull(Process::getProcessDataId)
                        .select(Process::getProcessId))
                .stream().map(Process::getProcessId).collect(Collectors.toList());
//        originalDataNodes.stream().filter(d->{
//            if(StringUtils.isBlank(d.getChildrenProcessId())){
//                return true;
//            }
//            return finalProcessIds.contains(d.getChildrenProcessId());
//        })
        // 只返回不是子流程的数据节点或者已经启用的子流程
        List<DataNode> finalDataNodes = originalDataNodes.stream()
                .filter(d -> StringUtils.isBlank(d.getChildrenProcessId()) || finalProcessIds.contains(d.getChildrenProcessId()))
                .collect(Collectors.toList());
        return Pagination.build(dataNodePage.getCurrent(), dataNodePage.getSize(), dataNodePage.getTotal(), dataNodeConverter.dos2vos(finalDataNodes));
    }
}




